From: Matthieu Gallien Date: Mon, 31 Mar 2025 13:07:36 +0000 (+0200) Subject: with release 32.0.0 md5 custom checksum is removed from bulkupload X-Git-Tag: archive/raspbian/3.16.7-1_deb13u1+rpi1~1^2~12^2^2~38^2~1 X-Git-Url: https://dgit.raspbian.org/%22http://www.example.com/cgi/success/%22http:/www.example.com/cgi/success?a=commitdiff_plain;h=89a0af11fa0a8e60ca237d98d2fd4c4bc0e510fe;p=nextcloud-desktop.git with release 32.0.0 md5 custom checksum is removed from bulkupload makes our fake server require an md5 custom checksum for bulk upload until version 32.0.0 starting with 32.0.0 this custom checksum must be empty Signed-off-by: Matthieu Gallien --- diff --git a/test/syncenginetestutils.cpp b/test/syncenginetestutils.cpp index e956716a8..e4a5d12a7 100644 --- a/test/syncenginetestutils.cpp +++ b/test/syncenginetestutils.cpp @@ -523,18 +523,19 @@ void FakePutReply::abort() emit finished(); } -FakePutMultiFileReply::FakePutMultiFileReply(FileInfo &remoteRootFileInfo, QNetworkAccessManager::Operation op, const QNetworkRequest &request, const QString &contentType, const QByteArray &putPayload, QObject *parent) +FakePutMultiFileReply::FakePutMultiFileReply(FileInfo &remoteRootFileInfo, QNetworkAccessManager::Operation op, const QNetworkRequest &request, const QString &contentType, const QByteArray &putPayload, const QString &serverVersion, QObject *parent) : FakeReply { parent } + , _serverVersion(serverVersion) { setRequest(request); setUrl(request.url()); setOperation(op); open(QIODevice::ReadOnly); - _allFileInfo = performMultiPart(remoteRootFileInfo, request, putPayload, contentType); + _allFileInfo = performMultiPart(remoteRootFileInfo, request, putPayload, contentType, _serverVersion); QMetaObject::invokeMethod(this, "respond", Qt::QueuedConnection); } -QVector FakePutMultiFileReply::performMultiPart(FileInfo &remoteRootFileInfo, const QNetworkRequest &request, const QByteArray &putPayload, const QString &contentType) +QVector FakePutMultiFileReply::performMultiPart(FileInfo &remoteRootFileInfo, const QNetworkRequest &request, const QByteArray &putPayload, const QString &contentType, const QString &serverVersion) { Q_UNUSED(request) QVector result; @@ -560,7 +561,19 @@ QVector FakePutMultiFileReply::performMultiPart(FileInfo &remoteRoot const auto standardChecksum = allHeaders[QStringLiteral("oc-checksum")]; Q_ASSERT(!fileName.isEmpty()); Q_ASSERT(modtime > 0); - Q_ASSERT(!expectedMd5Checksum.isEmpty()); + + auto components = serverVersion.split('.'); + const auto serverIntVersion = OCC::Account::makeServerVersion(components.value(0).toInt(), + components.value(1).toInt(), + components.value(2).toInt()); + + const auto md5ChecksumMandatory = serverIntVersion < OCC::Account::makeServerVersion(32, 0, 0); + + if (md5ChecksumMandatory) { + Q_ASSERT(!expectedMd5Checksum.isEmpty()); + } else { + Q_ASSERT(expectedMd5Checksum.isEmpty()); + } Q_ASSERT(!standardChecksum.isEmpty()); const auto standardChecksumComponents = standardChecksum.split(':'); @@ -579,12 +592,15 @@ QVector FakePutMultiFileReply::performMultiPart(FileInfo &remoteRoot Q_ASSERT(false); } - QCryptographicHash md5SumAlgorithm{QCryptographicHash::Algorithm::Md5}; - QCryptographicHash standardSumAlgorithm{standardHashAlgorithm}; + if (md5ChecksumMandatory) { + QCryptographicHash md5SumAlgorithm{QCryptographicHash::Algorithm::Md5}; + + md5SumAlgorithm.addData(onePartBody.toLatin1()); + const auto computedMd5Checksum = md5SumAlgorithm.result().toHex(); + Q_ASSERT(expectedMd5Checksum == computedMd5Checksum); + } - md5SumAlgorithm.addData(onePartBody.toLatin1()); - const auto computedMd5Checksum = md5SumAlgorithm.result().toHex(); - Q_ASSERT(expectedMd5Checksum == computedMd5Checksum); + QCryptographicHash standardSumAlgorithm{standardHashAlgorithm}; standardSumAlgorithm.addData(onePartBody.toLatin1()); const auto computedStandardChecksum = standardSumAlgorithm.result().toHex(); @@ -1143,7 +1159,7 @@ QNetworkReply *FakeQNAM::createRequest(QNetworkAccessManager::Operation op, cons reply = new FakeChunkMoveReply { info, _remoteRootFileInfo, op, newRequest, this }; } else if (verb == QLatin1String("POST") || op == QNetworkAccessManager::PostOperation) { if (contentType.startsWith(QStringLiteral("multipart/related; boundary="))) { - reply = new FakePutMultiFileReply { info, op, newRequest, contentType, outgoingData->readAll(), this }; + reply = new FakePutMultiFileReply { info, op, newRequest, contentType, outgoingData->readAll(), _serverVersion, this }; } } else if (verb == QLatin1String("LOCK") || verb == QLatin1String("UNLOCK")) { reply = new FakeFileLockReply{info, op, newRequest, this}; @@ -1168,6 +1184,11 @@ QNetworkReply * FakeQNAM::overrideReplyWithError(QString fileName, QNetworkAcces return reply; } +void FakeQNAM::setServerVersion(const QString &version) +{ + _serverVersion = version; +} + FakeFolder::FakeFolder(const FileInfo &fileTemplate, const OCC::Optional &localFileInfo, const QString &remotePath) : _localModifier(_tempDir.path()) { @@ -1189,7 +1210,8 @@ FakeFolder::FakeFolder(const FileInfo &fileTemplate, const OCC::OptionalsetUrl(QUrl(QStringLiteral("http://admin:admin@localhost/owncloud"))); _account->setCredentials(new FakeCredentials { _fakeQnam }); _account->setDavDisplayName(QStringLiteral("fakename")); - _account->setServerVersion(QStringLiteral("10.0.0")); + _account->setServerVersion(_serverVersion); + _fakeQnam->setServerVersion(_serverVersion); _journalDb = std::make_unique(localPath() + QStringLiteral(".sync_test.db")); _syncEngine = std::make_unique(_account, localPath(), OCC::SyncOptions{}, remotePath, _journalDb.get()); @@ -1312,6 +1334,17 @@ void FakeFolder::enableEnforceWindowsFileNameCompatibility() }); } +void FakeFolder::setServerVersion(const QString &version) +{ + if (_serverVersion == version) { + return; + } + + _serverVersion = version; + _account->setServerVersion(_serverVersion); + _fakeQnam->setServerVersion(_serverVersion); +} + FileInfo FakeFolder::currentLocalState() { QDir rootDir { _tempDir.path() }; diff --git a/test/syncenginetestutils.h b/test/syncenginetestutils.h index 817a138a5..44ed5edda 100644 --- a/test/syncenginetestutils.h +++ b/test/syncenginetestutils.h @@ -275,9 +275,9 @@ class FakePutMultiFileReply : public FakeReply { Q_OBJECT public: - FakePutMultiFileReply(FileInfo &remoteRootFileInfo, QNetworkAccessManager::Operation op, const QNetworkRequest &request, const QString &contentType, const QByteArray &putPayload, QObject *parent); + FakePutMultiFileReply(FileInfo &remoteRootFileInfo, QNetworkAccessManager::Operation op, const QNetworkRequest &request, const QString &contentType, const QByteArray &putPayload, const QString &serverVersion, QObject *parent); - static QVector performMultiPart(FileInfo &remoteRootFileInfo, const QNetworkRequest &request, const QByteArray &putPayload, const QString &contentType); + static QVector performMultiPart(FileInfo &remoteRootFileInfo, const QNetworkRequest &request, const QByteArray &putPayload, const QString &contentType, const QString &serverVersion); Q_INVOKABLE virtual void respond(); @@ -290,6 +290,8 @@ private: QVector _allFileInfo; QByteArray _payload; + + QString _serverVersion; }; class FakeMkcolReply : public FakeReply @@ -501,6 +503,8 @@ private: // monitor requests and optionally provide custom replies Override _override; + QString _serverVersion = QStringLiteral("10.0.0"); + public: FakeQNAM(FileInfo initialRoot); FileInfo ¤tRemoteState() { return _remoteRootFileInfo; } @@ -516,6 +520,8 @@ public: QNetworkReply *overrideReplyWithError(QString fileName, Operation op, QNetworkRequest newRequest); + void setServerVersion(const QString &version); + protected: QNetworkReply *createRequest(Operation op, const QNetworkRequest &request, QIODevice *outgoingData = nullptr) override; @@ -553,6 +559,7 @@ class FakeFolder OCC::AccountPtr _account; std::unique_ptr _journalDb; std::unique_ptr _syncEngine; + QString _serverVersion = QStringLiteral("10.0.0"); public: FakeFolder(const FileInfo &fileTemplate, const OCC::Optional &localFileInfo = {}, const QString &remotePath = {}); @@ -561,6 +568,8 @@ public: void enableEnforceWindowsFileNameCompatibility(); + void setServerVersion(const QString &version); + [[nodiscard]] OCC::AccountPtr account() const { return _account; } [[nodiscard]] OCC::SyncEngine &syncEngine() const { return *_syncEngine; } [[nodiscard]] OCC::SyncJournalDb &syncJournal() const { return *_journalDb; } diff --git a/test/testsyncengine.cpp b/test/testsyncengine.cpp index d1d182c82..ec603c17e 100644 --- a/test/testsyncengine.cpp +++ b/test/testsyncengine.cpp @@ -180,6 +180,38 @@ private slots: QCOMPARE(fakeFolder.currentLocalState(), fakeFolder.currentRemoteState()); } + void testDirUploadWithDelayedAlgorithmWithNewChecksum() { + FakeFolder fakeFolder{FileInfo::A12_B12_C12_S12()}; + fakeFolder.setServerVersion(QStringLiteral("32.0.0")); + fakeFolder.syncEngine().account()->setCapabilities({ { "dav", QVariantMap{ {"bulkupload", "1.0"} } } }); + + ItemCompletedSpy completeSpy(fakeFolder); + fakeFolder.localModifier().mkdir("Y"); + fakeFolder.localModifier().insert("Y/d0"); + fakeFolder.localModifier().mkdir("Z"); + fakeFolder.localModifier().insert("Z/d0"); + fakeFolder.localModifier().insert("A/a0"); + fakeFolder.localModifier().insert("B/b0"); + fakeFolder.localModifier().insert("r0"); + fakeFolder.localModifier().insert("r1"); + fakeFolder.syncOnce(); + QVERIFY(itemDidCompleteSuccessfullyWithExpectedRank(completeSpy, "Y", 0)); + QVERIFY(itemDidCompleteSuccessfullyWithExpectedRank(completeSpy, "Z", 1)); + QVERIFY(itemDidCompleteSuccessfully(completeSpy, "Y/d0")); + QVERIFY(itemSuccessfullyCompletedGetRank(completeSpy, "Y/d0") > 1); + QVERIFY(itemDidCompleteSuccessfully(completeSpy, "Z/d0")); + QVERIFY(itemSuccessfullyCompletedGetRank(completeSpy, "Z/d0") > 1); + QVERIFY(itemDidCompleteSuccessfully(completeSpy, "A/a0")); + QVERIFY(itemSuccessfullyCompletedGetRank(completeSpy, "A/a0") > 1); + QVERIFY(itemDidCompleteSuccessfully(completeSpy, "B/b0")); + QVERIFY(itemSuccessfullyCompletedGetRank(completeSpy, "B/b0") > 1); + QVERIFY(itemDidCompleteSuccessfully(completeSpy, "r0")); + QVERIFY(itemSuccessfullyCompletedGetRank(completeSpy, "r0") > 1); + QVERIFY(itemDidCompleteSuccessfully(completeSpy, "r1")); + QVERIFY(itemSuccessfullyCompletedGetRank(completeSpy, "r1") > 1); + QCOMPARE(fakeFolder.currentLocalState(), fakeFolder.currentRemoteState()); + } + void testLocalDelete() { FakeFolder fakeFolder{FileInfo::A12_B12_C12_S12()}; ItemCompletedSpy completeSpy(fakeFolder);